domains(redteam): add admina-redteam detection-efficacy suite#29
Conversation
stefanoferi
left a comment
There was a problem hiding this comment.
Reviewed across metrics, detector integration, gate/methodology, corpus integrity, and packaging. Ran the suite locally, recomputed the corpus hashes, and tested it against current main. Requesting changes on the items below before merge.
Verified
- No
eval/exec/subprocess/network/pickle; corpora SHA-256-verified before load (digests recomputed, match). - Metrics math correct: recall/precision/FPR/F1, zero-denominator →
None, recall over positives / FPR over negatives; baseline reduces to exact integer TP counts. - Measurement-only:
git diffoveradmina/domains|core|proxy|sdkis empty. run_suite()runs againstmain's post-refactor detectors; injection 21/37, loop 9/11 match the baseline.- No new runtime deps; package-data globs ship corpora in the wheel; tests cover tamper-detection, metric guards, bucketing, CLI e2e.
RUST_CAVEATemitted with every scorecard.
Blocking
- Gate can pass vacuously if a Python detector stops running.
tests/test_redteam_efficacy.py:42-43if cur is None: continueis meant for the absent Rust engine but also skips a dropped Python engine (LoopAdapter.engines()omitspythonwhen the[proxy]extra is missing) → green build on the worst-case regression. Treat Python as mandatory and Rust optional; assert the run covered every Python entry the baseline declares. - PII
recallis a type-level micro-average (metrics.py:47,runner.py:45-52) reported under the same"recall"key as the binary sample-level recall. Rename (type_recall) and document the averaging. - PII baseline is environment-dependent. The 100% Python recall was measured with spaCy; without
en_core_web_smthe redactor falls back to regex-only and diverges, which can trip the gate as a false regression. Pin the PII env (regex-only vs nlp) in the baseline metadata.
Process
- Rebase onto
main(~88 commits behind; no CI has run on this branch).main's MODEL_CARD §1 already states the engines are not behaviorally equivalent, so the equivalence mismatch resolves on rebase — verify §9 aligns with §1 and watch for apyproject.tomloverlap.
Non-blocking follow-ups (corpus size/denominators, label provenance, CLI entry point, fp-rate invariant, corpus edge cases) tracked in #37.
|
Perfetto grazie mille, mi metto al lavoro. |
1 — Gate "a vuoto" su detector Python assente. Logica del gate estratta in un modulo puro e testato (admina/redteam/gate.py::compare): Python obbligatorio, Rust opzionale. Una voce python dichiarata in baseline ma non eseguita ora fa fallire la build (prima passava verde). Aggiunta anche la reverse coverage: una voce python eseguita ma non dichiarata in baseline fallisce → una baseline troncata non passa a vuoto.
2 — recall PII ambiguo. Rinominato in type_recall (micro-average sui tipi di PII), distinto dal recall binario sample-level; semantica documentata in metrics.pii_scores, in runner e in MODEL_CARD 9.
3 — Baseline PII environment-dependent. La modalità di misura è ora ancorata nei metadata della baseline (nlp:<model>@<version> vs regex). Il gate confronta solo a parità di modalità; se un detector obbligatorio non riproduce la modalità ancorata fallisce con messaggio azionabile, anziché generare una falsa regressione. La versione del modello è inclusa nella firma perché un upgrade del NER cambierebbe i numeri a parità di nome.
Process — Rebase. Branch rebasato su main (0.10.1), pulito e senza conflitti: il §1 corretto ("not behaviorally equivalent") è ora in tree, allineato e con cross-reference. CI verde (45 test, ruff check/format ok); baseline riprodotta identica contro i detector di main — incluso il nuovo controllo Luhn sulle carte (i PAN del corpus sono Luhn-validi). schema_version portato a 2 per il cambio di shape della riga PII.
4c338d2 to
83193c5
Compare
|
Sistemato tutto come richiesto. |
stefanoferi
left a comment
There was a problem hiding this comment.
All three blocking items verified fixed (gate.py Python-mandatory + reverse coverage, type_recall, env-pinned baseline mode) — confirmed both statically and behaviorally: the gate fails actionably without the pinned spaCy model and reproduces the baseline with it. Full suite green locally (1113 passed) and on CI. Non-blocking follow-ups tracked in #37. Thanks for the quick turnaround.
Adds a measurement-only suite that runs the injection firewall, PII redactor and loop-breaker against SHA-256-sealed multilingual (EN/IT/FR/ES/DE) corpora on both the Python and Rust engines and emits recall/precision/FPR plus a per-class Python-vs-Rust matrix (admina/redteam/, CLI scripts/redteam.py). A soft CI gate (tests/test_redteam_efficacy.py) fails the build on recall regressions or new false positives against the committed baseline. Gate design (admina/redteam/gate.py::compare, pure and unit-tested): - Python detectors are mandatory, Rust is optional: a python entry declared in the baseline but not executed fails the build. Reverse coverage makes an executed-but-undeclared python entry fail too, so a truncated baseline cannot pass vacuously. - PII recall is reported as type_recall (a micro-average over PII types), distinct from the sample-level binary recall; semantics documented in metrics.pii_scores, the runner and MODEL_CARD §9. - The PII measurement mode is pinned in the baseline metadata (nlp:<model>@<version> vs regex). The gate only compares metrics measured in the same mode; a mandatory detector that does not reproduce the pinned mode fails with an actionable message instead of surfacing a false regression. The model version is part of the signature because a NER upgrade changes the numbers under the same model name. schema_version bumped to 2 for the PII row shape change. The baseline reproduces identically against main's detectors, including the Luhn check on cards (corpus PANs are Luhn-valid). Co-authored-by: Stefano Noferi <stefanoferi@users.noreply.github.com>
|
Thanks for the merge |
Summary
admina-redteam: una suite riproducibile di efficacia di detection che misura quantoi detector di Admina riconoscono gli attacchi (recall / precision / F1 / FPR), non solo
quanto sono veloci. Esegue il firewall anti-injection, il redattore PII e il loop-breaker su
corpora originali multilingue (EN/IT/FR/ES/DE) sigillati con hash, su entrambi i motori
(Python e Rust), e produce uno scorecard JSON + Markdown con la matrice Python-vs-Rust per
classe. Un gate CI "soft" fa fallire la build su regressioni di recall o nuovi falsi
positivi rispetto a un baseline committato. È solo misurazione: nessun detector viene
modificato. Risponde al gap dichiarato in
MODEL_CARD.md("Admina non spedisce una suite dibenchmark di accuratezza… i contributi sono benvenuti e prioritari").
Type
Primo baseline misurato (corpus proprio di Admina, non un punteggio PINT di terze parti)
Gap reali emersi (matrice completa per classe:
python scripts/redteam.py --format md):hyphenation) che il Python cattura al 100%: al motore Rust manca il passaggio
normalize_text(), quindi il path "veloce" è anche il meno accurato.che il motore Rust (finestra piena) invece cattura.
PERSON/ORGsu frasi negative non inglesi (il Rust, solo-regex, non li produce).Come si usa
python scripts/redteam.py # scorecard completo, entrambi i motori python scripts/redteam.py --corpus injection --engine python --format mdIl gate CI è in
tests/test_redteam_efficacy.pye confronta l'esecuzione live con ilcommittato
admina/redteam/baselines/baseline.json.Design
admina/redteam/(metriche → loader corpora → adapter dei detector → runner →report), CLI sottile
scripts/redteam.py, e un test pytest che gira dentro il jobpython-testsesistente (nessun nuovo workflow CI).caricamento (e li dichiara in
[tool.setuptools.package-data]così finiscono nel wheel).admina.domains).null(saltate dal gate, non trattate come regressioni);il motore Rust viene saltato se
admina_coreè assente (come intest_firewall_parity.py).Note tecniche
numpy/scikit-learn(extra[proxy], già esistente):l'adapter del loop fa degradare con grazia (motore Python segnato non disponibile) se non
sono installati, invece di andare in errore.
admina_core0.9.3 (wheel PyPI). Il gate salta il Rustse l'engine è assente; non gestisce un eventuale drift di versione del wheel — felice di
vincolare la versione o rendere il confronto Rust "advisory" se preferite.
Fuori scope
Classificatore ML/semantico per injection; adapter per dataset esterni
(
garak/PromptInject); chiusura del gap di parità del firewall Rust (questa suite ne è ilcriterio d'accettazione); corpora più ampi e con più lingue.
Domande
admina/redteam/oadmina/bench/efficacy/?MODEL_CARD.md(attuale) o undocs/efficacy.mddedicato?domains(redteam):(CONTRIBUTING non ha uno scopebench/test).Checklist
ruffebanditpulitidomains(redteam):